package com.module.ble.repo

import com.common.base.app.extras.no
import com.module.ble.db.HealthExaManager
import com.module.ble.db.HeartRateTableQueryHelper
import com.module.ble.db.table.UserHeartRate
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
import java.util.concurrent.atomic.AtomicLong

/**
 * 作者：sosou
 * <p>
 * 版本：1.0
 * <p>
 * 创建日期：2024/10/18
 * <p>
 * 描述：仓库类，所有心率相关的数据操作都在此类中进行，数据库的增、删、改、查操作
 * <p>
 * 修订历史：
 */
class HeartRateRepo private constructor() {

    private val refreshTrigger = MutableStateFlow(0)

    companion object {
        val instance by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { HeartRateRepo() }
    }

    private val dao = HealthExaManager.mHeartRateDao

//    private val scope = CoroutineScope(Dispatchers.IO)
    // 使用单线程调度器避免并发冲突
    @OptIn(ExperimentalCoroutinesApi::class)
    private val scope = CoroutineScope(Dispatchers.IO.limitedParallelism(1))

    // 原子变量保证线程安全
    private val lastHeartRateTimesTamp = AtomicLong(0)
    private var lastHeartRateTamp :Int = 0

    /**
     * 查找所有数据
     */
    fun findAll(): List<UserHeartRate>? {
        //数据库查找所有数据
        return dao?.findAll()
    }

    /**
     * 查找所有未上传数据
     */
    fun findAllNotUp(): List<UserHeartRate>? {
        //数据库查找所有数据
        return dao?.findAllNotUp()
    }


    /**
     * 查找所有数据
     */
    @OptIn(ExperimentalCoroutinesApi::class)
    fun findAllFlow(): Flow<List<UserHeartRate>> = refreshTrigger.flatMapLatest { dao?.findLatestDayFlow() ?: flowOf(emptyList())}

    /**
     * 根据时间范围查询心率数据
     */
    fun findByTimeRange(startTime:Long, endTime:Long): List<UserHeartRate>? {
        //数据库查找所有数据
        return dao?.findByTimeRange(startTime,endTime)
    }

    /**
     * 根据时间范围查询心率数据（Flow版本）
     */
    @OptIn(ExperimentalCoroutinesApi::class)
    fun findByTimeRangeFlow(startTime:Long, endTime:Long): Flow<List<UserHeartRate>> = refreshTrigger.flatMapLatest { dao?.findByTimeRangeFlow(startTime,endTime) ?: flowOf(emptyList())}

    /**
     * 根据传入时间戳查询该时间戳当天的所有数据
     */
    fun findByOneDay(timestamp: Long): List<UserHeartRate>? {
        //数据库查找所有数据
        return dao?.findByDay(timestamp)
    }

    /**
     * 根据多个时间段查询睡眠数据
     * @param timeRanges 时间段数组，每个Pair的first为开始时间戳，second为结束时间戳
     * @return 查询到的睡眠数据列表
     */
    fun findByMultiTimeRanges(timeRanges: List<Pair<Long, Long>>): List<UserHeartRate>? {
        if (timeRanges.isEmpty()) return emptyList()

        val query = HeartRateTableQueryHelper.createMultiTimeRangeQuery(timeRanges)
        return dao?.findByCustomQuery(query)
    }

    /**
     * 根据多个时间段查询睡眠数据（Flow版本）
     * @param timeRanges 时间段数组，每个Pair的first为开始时间戳，second为结束时间戳
     * @return Flow<List<UserHeartRate>>
     */
    @OptIn(ExperimentalCoroutinesApi::class)
    fun findByMultiTimeRangesFlow(timeRanges: List<Pair<Long, Long>>): Flow<List<UserHeartRate>> {
        if (timeRanges.isEmpty()) return flowOf(emptyList())

        return refreshTrigger.flatMapLatest {
            val query = HeartRateTableQueryHelper.createMultiTimeRangeQuery(timeRanges)
            dao?.findByCustomQueryFlow(query) ?: flowOf(emptyList())
        }
    }

    /**
     * 根据传入时间戳查询该时间戳当天的最新数据
     */
    fun findLatestByDay(timestamp: Long): UserHeartRate? {
        //数据库查找所有数据
        return dao?.findLatestByDay(timestamp)
    }

    /**
     * 插入数据
     */
    fun add2DB(data: UserHeartRate?) {
        data?.let { dataIt->
            scope.launch {
                // 添加时间锁机制（60000ms内仅允许执行一次）PS：回调存在一分钟内返回两次重复数据情况
//                val now = System.currentTimeMillis()
//                if (now - lastHeartRateTimestamp.get() < 1000L && lastHeartRateTamp == dataIt.heartRate) return
//                lastHeartRateTimestamp.set(now) // 必须先更新时间戳再执行后续逻辑
                val currentTimeMillis = System.currentTimeMillis()
                val lastTimestamp = lastHeartRateTimesTamp.get()
                if ((currentTimeMillis - lastTimestamp <= 60000L || !lastHeartRateTimesTamp.compareAndSet(lastTimestamp, currentTimeMillis)) && lastHeartRateTamp == dataIt.heartRate) return@launch
                lastHeartRateTamp = dataIt.heartRate
                dao?.insert(dataIt)
            }
        }
    }

    suspend fun add2DBAndFetch(data: UserHeartRate?): List<UserHeartRate>? {
        data?.let { dataIt->
            scope.launch {
                dao?.insert(dataIt)
            }
        }
        return dao?.findAll()
    }

    /**
     * 插入数据
     */
    fun add2DB(mList: List<UserHeartRate>) {
        mList.isEmpty().no {
            scope.launch {
                dao?.insert(mList)
            }
        }
    }

    fun insertOrUpdate(record: UserHeartRate) {
        val existing = dao?.findMessageByTime(record.createdTime)
        if (existing != null) {
            // 更新现有记录的值
            existing.heartRate = record.heartRate
            dao?.update(existing)
        } else {
            // 插入新记录
            dao?.insert(record)
        }
    }

    fun insertDistinct(mList: List<UserHeartRate>, batchSize: Int = 500) {
        if (mList.isNullOrEmpty()) return
        scope.launch {
            // 分批处理
            mList.chunked(batchSize).forEach { batch ->
                dao?.insert(batch) // 直接插入整个批次
            }
        }
    }
    
    /**
     * 批量智能插入：保护已上传的数据
     */
    fun insertBatchSmart(mList: List<UserHeartRate>, batchSize: Int = 500) {
        if (mList.isNullOrEmpty()) return
        scope.launch {
            // 获取所有时间戳
            val timeStamps = mList.map { it.createdTime }
            val existingTimes = dao?.getExistingTimes(timeStamps) ?: emptyList()

            // 分为新数据和需要检查的数据
            val newData = mList.filter { it.createdTime !in existingTimes }
            val existingData = mList.filter { it.createdTime in existingTimes }

            // 直接插入新数据
            if (newData.isNotEmpty()) {
                newData.chunked(batchSize).forEach { batch ->
                    dao?.insert(batch)
                }
            }

            // 检查已存在数据的sysStat状态
            existingData.forEach { newRecord ->
                val existing = dao?.findMessageByTime(newRecord.createdTime)
                if (existing?.sysStat == 0) {
                    // 只更新未上传的数据
                    existing.heartRate = newRecord.heartRate
                    dao?.update(existing)
                }
            }
        }
    }

    fun updateBatch(mList: List<UserHeartRate>, batchSize: Int = 500) {
        if (mList.isNullOrEmpty()) return
        scope.launch {
            // 分批处理
            mList.chunked(batchSize).forEach { batch ->
                dao?.update(batch) // 分配更新
            }
        }
    }

    /**
     * 删除数据库中数据
     */
    private fun del2DB(data: UserHeartRate?) {
        data?.let { dataIt->
            scope.launch {
                dao?.delete(dataIt)
            }
        }
    }

    /**
     * 删除数据库中数据
     */
    fun deleteAll(){
        scope.launch {
            dao?.deleteAll()
        }
    }

    /**
     * 自动触发 Flow 的更新，进而更新 LiveData
     */
    fun refreshData() {
        refreshTrigger.value += 1
    }

    /**
     *
     */
    fun updateAllFirmNameToOne() {
        scope.launch {
            dao?.updateAllFirmNameToOne()
        }
    }

    /**
     *
     */
    fun updateAllSysStatToZero() {
        scope.launch {
            dao?.updateAllSysStatToZero()
        }
    }

    /**
     *
     */
    fun deleteInvalidHeartRateData() {
        scope.launch {
            dao?.deleteInvalidHeartRateData()
        }
    }
}